#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys
import os
import os.path
from . import VERSION
from datetime import datetime
from mako.template import Template
from mako.lookup import TemplateLookup
from .xmlconfig import (init_parser, parse_config_file)
from .commdef import (
        to_pascal, to_camel, to_lower,
        PACKAGE_NAME_SEPERATOR, CommandType, ResultType, 
        DbType, MatchType, Direction, DynamicTextType, 
        DbModule, DbParameter, DbStatement, DbDynamic)
from .log import (set_filelogger, set_log_level,
        log_error, log_warn, log_info, log_verbose, log_title,
        log_good, close_log, LoggerLevel)

tpl_lookup = None

def render_csharp(module):
    '''
    '''
    return __render('csharp.tpl', to_pascal(module.name) + 'Provider.cs', module)

def render_java(module):
    '''
    '''
    return __render('java.tpl', to_pascal(module.name) + 'Provider.java', module)

def __load_template_file(basedir, filename):
    '''
    '''
    assert basedir, 'Argument "basedir" cannot be null or empty!'
    assert filename, 'Argument "filename" cannot be null or empty!'

    full_filename = os.path.join(basedir, filename)

    if not os.path.isfile(full_filename):
        return None, None

    with open(full_filename, 'rt', encoding = 'utf-8') as f:
        log_verbose('Loading template "%s".' % full_filename)

        content = f.read()
        f.close()

    fn, ext = os.path.splitext(filename)
    return fn.lower(), content 

def __load_template_files():
    '''
    '''
    assert __file__, 'Envionment "__file__" cannot be null or empty!'

    basedir = os.path.dirname(os.path.realpath(__file__))
    files = os.listdir(basedir)
    for f in files:
        if not f:
            continue

        # Find *.tpl
        if f.lower().endswith('.tpl'):
            name, content = __load_template_file(basedir, f)
            if name:
                yield name, content

def __init_lookup():
    '''
    '''
    global tpl_lookup

    tpl_lookup = TemplateLookup(
            filesystem_checks = False, 
            module_directory = '.') 

    for (tpl_name, tpl_content) in __load_template_files():
        tpl_lookup.put_string(tpl_name + '.tpl', tpl_content)

    return tpl_lookup

def __module_writer(source, outputpath):
    '''
    '''
    with open(outputpath, 'wt') as f:
        os.write(f, source)
        os.close(f)

def __render(tpl_file, code_file, module):
    '''
    '''
    assert tpl_file, 'Argument "tpl_file" cannot be null or empty!'
    assert code_file, 'Argument "code_file" cannot be null or empty!'

    if not module:
        return ''

    tpl = tpl_lookup.get_template(tpl_file)

    log_verbose('Writing code "%s".' % code_file)
    with open(code_file, 'wt', encoding = 'utf-8') as cf:
        cf.write(tpl.render(module = module, datepoint = datetime.now()))
        cf.close()

def main(source_file = 'statements.xml', root_package = 'my_lib.data_access', log_file = None, verbose = False):
    '''
    '''
    if log_file:
        set_filelogger(log_file)

    if verbose:
        set_log_level(LoggerLevel.VERBOSE)
    else:
        set_log_level(LoggerLevel.INFO)

    log_info('''\
Autodb %s 
            ''' % VERSION)

    start_time = datetime.now()
    log_info('Starting time: %04d/%02d/%02d %02d:%02d:%02d' % (
            start_time.year,
            start_time.month,
            start_time.day,
            start_time.hour,
            start_time.minute,
            start_time.second))

    errors = []
    warns = []

    log_title('\nParsing config file.\n')

    init_parser()
    try:
        modules = list(parse_config_file(source_file, root_package =
            root_package))
    except Exception as e:
        errors.append(e)
        modules = []

    log_title('\nInitializing template(s).\n')

    __init_lookup()

    log_title('\nCreating code file(s).\n')

    for module in modules:
        try:
            render_csharp(module)
        except Exception as e:
            errors.append(e)

    if errors:
        log_error('\nFailed to build "%s".\n' % source_file)
    else:
        log_good('\nSucceeded to build "%s".\n' % source_file)

    log_info('Errors: %d' % len(errors))
    log_info('Warns: %d' % len(warns))
    for i, err in enumerate(errors):
        log_error('  Error (%d): %s' % (i + 1, err))
    for i, err in enumerate(warns):
        log_warn(' Warn (%d): %s' % (i + 1, err))
    log_info('')

    elapsed_time = datetime.now() - start_time
    log_info('Elapsed time: %d.%04ds.' % (
        elapsed_time.seconds,
        elapsed_time.microseconds / 1000))

    close_log()

    if errors:
        return 1
    else:
        return 0
